<!DOCTYPE html><html>
<head>
<title>Sprite.js test suites</title>
<meta name = "viewport" content = "user-scalable=no, width=device-width">
<style>
    html, body{
        font-family:sans-serif;
    }

    .result {
        width:23%;
        float:left;
        height:auto;
        padding:0.2em;
        margin:0.2em;
        border-left:20px #2a2 solid;
    }

    .fail {
        border-left:20px #e11 solid;
    }

</style>
</head>
<body>

<h1>Sprite.js test suites</h1>

<p id="infos"></p>

<div id="result" style="font-size:0.90em"></div>

</body>
<script src="../sprite.js"></script>
<script src="../lib/collision.js"></script>
<script>

window.onload = function() {

    var result = document.getElementById('result');
    var infos = document.getElementById('infos');
    result.style['height'] = (window.window.innerHeight - 100) + 'px';
    var test_runned = 0;
    var failed_test = 0;

    function insertResult(desc, message, fail) {
        test_runned ++;
        if(fail) {
            failed_test ++;
            result.innerHTML += '<div class="result fail">' + desc + ' failed.<br><strong>Because</strong><br>' + message + '</div>';
        } else {
            result.innerHTML += '<div class="result">' + desc + '</div>';
        }
        infos.innerHTML = test_runned + " test runned. " + failed_test + " test failed.";
    }

    function assertTrue(value, desc) {
        if(value) {
            insertResult(desc);
        } else {
            insertResult(desc, value+' is not true', true);
        }
    }
    function assertFalse(value, desc) {
        if(!value) {
            insertResult(desc);
        } else {
            insertResult(desc, value+'" is not false', true);
        }
    }

    function assertGreater(v1, v2, desc) {
        if(v1 > v2) {
            insertResult(desc);
        } else {
            insertResult(desc, v1+'" is not greater than "'+v2+'"', true);
        }
    }

    function assertEqual(value1, value2, desc) {
        if(typeof value1 == "object")
            value1 = JSON.stringify(value1);
        if(typeof value2 == "object")
            value2 = JSON.stringify(value2);
        if(value1 === value2) {
            insertResult(desc);
        } else {
            insertResult(desc, value1+' not equal to '+value2, true);
        }
    }

    function assertNotEqual(value1, value2, desc) {
        if(typeof value1 == "object")
            value1 = JSON.stringify(value1);
        if(typeof value2 == "object")
            value2 = JSON.stringify(value2);
        if(!(value1 === value2)) {
            insertResult(desc);
        } else {
            insertResult(desc, value1+' equal to '+value2, true);
        }
    }

    var scene = sjs.Scene();
    var sp1 = scene.Sprite();

    assertEqual(sp1.layer.name, "default", "Assert that the default layer is set");

    sp1.size(10, 10);
    sp1.move(10, 10);

    assertFalse(sp1.isPointIn(0, 0), "isPointIn test1");
    assertFalse(sp1.isPointIn(21, 21), "isPointIn test2");
    assertFalse(sp1.isPointIn(15, 21), "isPointIn test3");

    assertTrue(sp1.isPointIn(15, 15), "isPointIn test4");
    assertFalse(sp1.isPointIn(15, 20), "isPointIn test5");

    var sp2 = scene.Sprite();
    sp2.size(10, 10);
    sp2.move(15, 10);

    var sp3 = scene.Sprite();
    sp3.size(10, 10);
    sp3.move(21, 10);

    assertTrue(sp1.collidesWith(sp1), "A sprite should collides with itself");
    assertTrue(sp1.collidesWith(sp2), "collidesWith test2");
    assertTrue(sp2.collidesWith(sp1), "collidesWith test3");

    assertFalse(sp1.collidesWith(sp3), "collidesWith test4");
    assertTrue(sp2.collidesWith(sp3), "collidesWith test5");

    var sp1 = scene.Sprite();
    sp1.size(100, 200);

    assertTrue(sp3.collidesWith(sp1), "collidesWith test5");
    assertTrue(sp1.collidesWith(sp3), "collidesWith test6");

    var sp1 = scene.Sprite();
    sp1.size(10, 10);
    sp1.move(10, 10);

    var sp2 = scene.Sprite();
    sp2.size(10, 10);
    sp2.move(15, 10);

    assertEqual(sp1.distance(sp2), 5,  "distance 2 sprites 1");
    sp2.move(0, 5);
    assertEqual(sp1.distance(sp2), Math.sqrt(50),  "distance 2 sprites 2");

    assertEqual(sp1.distance(15, 15), 0,  "Point distance test 1");
    assertEqual(sp1.distance(20, 15), 5,  "Point distance test 2");
    assertEqual(sp1.distance(15, 20), 5,  "Point distance test 3");
    assertEqual(sp1.distance(20, 20), Math.sqrt(5*5+5*5),  "Point distance test 4");

    // Sprite instanciation tests
    var fakelayer = {
        dom:{appendChild:function(){}},
        sprites:[]
    }

    var sp1 = scene.Sprite(false, {x:40, y:50, w:30, h:25, layer:fakelayer});
    assertEqual(sp1.x, 40,  "init position 1");
    assertEqual(sp1.y, 50,  "init position 2");
    assertEqual(sp1.w, 30,  "init size 1");
    assertEqual(sp1.h, 25,  "init size 2");
    assertEqual(sp1.layer, fakelayer,  "init layer");

    var layer = scene.layers['default'];
    var sp1 = layer.Sprite(false, {w:30});
    assertEqual(sp1.w, 30,  "init size with layer");

    var sp1 = scene.Sprite(false, {position:[60, 60], size:[55, 65], toto:5, layer:fakelayer, xoffset:20, yoffset:21, xscale:2});
    assertEqual(sp1.x, 60,  "init position 3");
    assertEqual(sp1.y, 60,  "init position 4");
    assertEqual(sp1.w, 55,  "init size 3");
    assertEqual(sp1.h, 65,  "init size 4");

    assertEqual(sp1.xoffset, 20,  "init xoffset");
    assertEqual(sp1.yoffset, 21,  "init yoffset");
    assertEqual(sp1._dirty['xoffset'], true, "dirty offset");
    assertEqual(sp1._dirty['yoffset'], true, "dirty offset");

    assertEqual(sp1.xscale, 2,  "init xscale");
    assertEqual(sp1._dirty['xscale'], true, "dirty xscale");

    assertEqual(sp1.xoffset, 20,  "init xoffset");
    assertEqual(sp1.yoffset, 21,  "init yoffset");
    assertEqual(sp1._dirty['xoffset'], true, "dirty offset");
    assertEqual(sp1._dirty['yoffset'], true, "dirty offset");

    assertEqual(sp1.toto, undefined,  "init undefined");
    assertEqual(sp1.layer, fakelayer,  "init layer");

    var sp1 = scene.Sprite(false, {position:[-5, -5], size:[10, 10]});

    assertEqual(sp1.edges(),
      [[-5,5.000000000000001],[5.000000000000001,5],[5.000000000000001,-5],[-5,-5]],  "edges function 1");

    sp1.angle = Math.PI / 2.0;

    assertEqual(sp1.edges(),
      [[-5,-5],[-5,5.000000000000001],[5.000000000000001,5],[4.999999999999999,-5]],  "edges function 2");

    sp1.angle += Math.PI / 4.0;

    assertFalse(sjs.math.lineSide(0, 0, 10, 10, 2, 1), "lineSide");
    assertTrue(sjs.math.lineSide(0, 0, 10, 10, 1, 2), "lineSide");
    assertFalse(sjs.math.lineSide(10, 10, 0, 0, 1, 2), "lineSide");
    assertFalse(sjs.math.lineSide(-5, 5, 5, 5, 4.8, 4.8), "lineSide");
    assertFalse(sjs.math.lineSide(-5, 5, 5, 5, 1, 1), "lineSide");
    assertTrue(sjs.math.lineSide(-5, 5, 5, 5, 5.1, 5.1), "lineSide");


    sp1.angle = 0;
    assertTrue(sp1.isPointIn(0, 0), "isPointIn with with no angle 1");
    //assertTrue(sp1.isPointIn(0, 0), "isPointIn with no angle 1");

    assertTrue(sp1.isPointIn(4.8, 4.8), "isPointIn with no angle 2");
    //assertTrue(sp1.isPointIn(4.8, 4.8), "isPointIn with no angle 2");

    assertFalse(sp1.isPointIn(5.2, 5.2), "isPointIn with no angle 3");
    assertFalse(sp1.isPointIn(5.2, 5.2), "isPointIn with no angle 3");


    sp1.angle = Math.PI / 2.0;
    assertFalse(sp1.isPointIn(5.1, 5.1), "isPointIn with angle Math.PI / 2.0");
    assertTrue(sp1.isPointIn(4.8, 4.8), "isPointIn with angle Math.PI / 2.0");

    sp1.angle = Math.PI / 4.0;
    assertFalse(sp1.isPointIn(5.1, 5.1), "isPointIn with Math.PI / 4.0");
    assertFalse(sp1.isPointIn(4.8, 4.8), "isPointIn with Math.PI / 4.0");
    assertTrue(sp1.isPointIn(6.5, 0), "isPointIn with Math.PI / 4.0");
    assertFalse(sp1.isPointIn(8, 0), "isPointIn with Math.PI / 4.0");

    var sp1 = scene.Sprite(false, {position:[-10, -5], size:[20, 10]});
    sp1.angle = 0
    assertTrue(sp1.isPointIn(9, 0), "isPointIn 1");
    assertTrue(sp1.isPointIn(9, -4.5), "isPointIn 2");
    assertTrue(sp1.isPointIn(9, 4.5), "isPointIn 3");
    assertFalse(sp1.isPointIn(11, 4.5), "isPointIn 4");
    assertFalse(sp1.isPointIn(0, 6), "isPointIn 5");
    assertFalse(sp1.isPointIn(-11, 0), "isPointIn 6");
    assertTrue(sp1.isPointIn(-9, 4.5), "isPointIn 7");
    assertTrue(sp1.isPointIn(-9, -4.5), "isPointIn 8");

    sp1.angle = Math.PI / 2.0;
    assertTrue(sp1.isPointIn(-4.8, 9.9), "isPointIn 9");
    assertTrue(sp1.isPointIn(4.8, -9.9), "isPointIn 10");
    assertFalse(sp1.isPointIn(0, 11), "isPointIn 11");
    assertFalse(sp1.isPointIn(9, 0), "isPointIn 12");

    sp1.angle = Math.PI / 4.0;

    assertTrue(sp1.isPointIn(6, 6), "isPointIn 13");
    assertTrue(sp1.isPointIn(7, 7), "isPointIn 14");
    assertFalse(sp1.isPointIn(8, 8), "isPointIn 15");
    var max = 10.0 * Math.cos(Math.PI / 4.0);
    assertTrue(sp1.isPointIn(max, max), "isPointIn 16");
    max = max + 0.1;
    assertFalse(sp1.isPointIn(max, max), "isPointIn 17");

    var sp1 = scene.Sprite(false, {position:[10, 10], size:[10, 10]});
    var sp2 = scene.Sprite(false, {position:[20.1, 10], size:[10, 10]});

    assertFalse(sp1.collidesWith(sp2), "collidesWith 1");
    assertFalse(sp1.collidesWith(sp2), "collidesWith 2");
    sp1.angle = 0.01;
    assertFalse(sp1.collidesWith(sp2), "collidesWith 3");
    sp2.angle = 0.01;
    assertFalse(sp1.collidesWith(sp2), "collidesWith 4");
    sp2.angle = Math.PI / 4.0;
    assertTrue(sp1.collidesWith(sp2), "collidesWith 5");

    var sp1 = scene.Sprite(false, {position:[0, 200], size:[200, 100]});
    var sp2 = scene.Sprite(false, {position:[50, 0], size:[20, 20]});
    var nbCollision = 0;
    sp2.rv = 0.1;
    for(var i=0; i<100; i++) {
        sp2.yv += 0.5;
        sp2.applyVelocity();
        if(sp2.collidesWith(sp1))
            nbCollision += 1;
    }
    assertTrue(nbCollision > 0, "collidesWith 6")

    math = sjs.math;

    assertEqual(math.hypo(5, 5), Math.sqrt(50), "Test pythagore theorem")
    assertEqual(math.mod(3, 2), 1, "Test modulo 1")
    assertEqual(math.mod(-1, 2), 1, "Test modulo 2")

    assertEqual(math.normalVector(2, 2), {x:(2/math.hypo(2, 2)), y:(2/math.hypo(2, 2))}, "Test normal vector 1")
    assertEqual(math.normalVector(2, 2, math.hypo(2, 2)), {x:2, y:2}, "Test normal vector 2")

    var ticker = scene.Ticker(10, function() {});
    ticker.run();
    var ct = undefined;

    setTimeout(function() {
        ticker.pause();
        ct = ticker.currentTick;
        ticker.resume();
    }, 20);

    setTimeout(function() {
        ticker.pause();
        assertGreater(ticker.currentTick, ct, "Test that the currentTick value of the ticker still increase after a pause");
    }, 100);

    var obj = {}
    obj[sp1] = 3;

    assertEqual(obj[sp1], 3, "Test object hash access with a Sprite 1");
    sp1.move(10, 5);
    assertEqual(obj[sp1], 3, "Test object hash access with a Sprite 2");

    var sp1 = scene.Sprite();
    var sp2 = scene.Sprite();
    assertNotEqual(sp1.id, sp2.id, "Test that it's not possible to create 2 Sprites with equal ids.");

    var sp1 = scene.Sprite(false, false);
    assertEqual(sp1.layer, null, "Test that it's possible to create a layer less Sprite object 1.");
    assertEqual(sp1.dom, null, "Test that a layer less Sprite doesn't have dom.");

    // testing the shape redefinition
    var sp1 = scene.Sprite();
    sp1.size(10, 10);
    sp1.move(10, 10);

    sp1.shape = {x:0, y:0, w:10, h:10, type:"rectangle"};
    assertTrue(sp1.collidesWith(sp1), "Shape redefinition 1: a sprite should collides with itself");
    sp1.shape = {x:1, y:1, w:8, h:8, type:"rectangle"};
    assertTrue(sp1.collidesWith(sp1), "Shape redefinition 2: a sprite should collides with itself");

    var sp2 = scene.Sprite();
    sp2.size(10, 10);
    sp2.move(10, 10);
    sp1.shape = {x:0, y:0, w:10, h:10, type:"rectangle"};
    assertTrue(sp1.collidesWith(sp2), "Shape redefinition 3: sprite collides with another");
    sp1.shape = {x:1, y:1, w:8, h:8, type:"rectangle"};
    assertTrue(sp1.collidesWith(sp2), "Shape redefinition 4: sprite collides with another");
    assertTrue(sp2.collidesWith(sp1), "Shape redefinition 5: sprite collides with another");

    var cycle = scene.Cycle(
    [[1, 1, 1],
     [2, 2, 1],
     [3, 3, 1]]
    );

    assertEqual(cycle.cycleDuration, 3);

    assertEqual(cycle.currentTripletIndex, undefined, "Default cycle index is undefined");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 1, "Cycle index should be 1");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 2, "Cycle index should be 2");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 1, "Cycle index should be 1");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 2, "Cycle index should be 2");
    cycle.next(1);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");

    var cycle = scene.Cycle(
    [[1, 1, 3],
     [2, 2, 3],
     [3, 3, 3]]
    );

    assertEqual(cycle.cycleDuration, 9);

    assertEqual(cycle.currentTripletIndex, undefined, "Default cycle index is undefined");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 1, "Cycle index should be 1");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 2, "Cycle index should be 2");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 1, "Cycle index should be 1");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 2, "Cycle index should be 2");
    cycle.next(3);
    assertEqual(cycle.currentTripletIndex, 0, "Cycle index should be 0");


};
</script>
</html>
